/*************************************************************************
                           Mere  -  description
                             -------------------
    début                : Mere
    copyright            : (C) Mere par rcatolino
    e-mail               : 
*************************************************************************/

//---------- Réalisation de la tâche <Mere> (fichier Mere.cpp) ---

/////////////////////////////////////////////////////////////////  INCLUDE
//-------------------------------------------------------- Include système
using namespace std;
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <iostream>
//------------------------------------------------------ Include personnel
#include "/public/tp/tp-multitache/Outils.h"
#include "/public/tp/tp-multitache/Heure.h"
#include "/public/tp/tp-multitache/Generateur.h"
#include "/public/tp/tp-multitache/Menu.h"
#include "/public/tp/tp-multitache/Voiture.h"
#include "Mere.h"
#include "Feu.h"
#include "MenuTache.h"
#include "GestionPriorite.h"
///////////////////////////////////////////////////////////////////  PRIVE
//------------------------------------------------------------- Constantes
static const int DROITS = 0660;
//------------------------------------------------------------------ Types

//---------------------------------------------------- Variables statiques
static pid_t pidHeure;
static pid_t pidGenerateur;
static pid_t pidFeu;
static pid_t pidGestionPrioriteOuest;
static pid_t pidGestionPrioriteEst;
static pid_t pidGestionPrioriteNord;
static pid_t pidGestionPrioriteSud;
static pid_t pidMenu;
//------------------------------------------------------ Fonctions privées

//////////////////////////////////////////////////////////////////  PUBLIC
//---------------------------------------------------- Fonctions publiques
int main ( int arg, char** argv )
{
	// Initialistion des composants :
    InitialiserApplication( XTERM );

	// Création de la boîte aux lettres BALVoiture
	int BALVoiture = msgget ( (key_t)12 , DROITS | IPC_CREAT );
	cerr << "creation de BALVOiture " << BALVoiture << endl;
	
	// Création des mémoires partagées MTempoFeu et MEtatFeu
	int MTempoFeu = shmget ( (key_t)13, 1 , DROITS | IPC_CREAT );
	int MEtatFeu = shmget ( (key_t)14, 1 , DROITS | IPC_CREAT );
	cerr << "creation des Shm tempo et etat pour le feu  " << MTempoFeu << MEtatFeu << endl;
	
	//Attachement de MTempoFeu et MEtatFeu
	void *ATempoFeu = shmat( MTempoFeu, NULL, DROITS );
	void *AEtatFeu = shmat( MEtatFeu, NULL, DROITS );


	// Création des sémaphores correspondants aux mémoires partagées
	int SFeu = semget ( (key_t)15, 2, DROITS | IPC_CREAT ); //Avec un sémaphore contenant deux sémaphores élémentaires?
	//int SEtatFeu = semget ( (key_t)16, 1, DROITS | IPC_CREAT );
	cerr << "creation du sémaphore d'acces aux Shm de heu " << SFeu << endl; 
	//Initialisation des sémaphores : ils sont dispo au début
	semctl ( SFeu,0,SETVAL,1 );
	semctl ( SFeu,1,SETVAL,1 );

	// Création de la tâche Heure
	pidHeure = ActiverHeure();
	cerr << "création de la tache heure "<<endl;

	// Création de la tâche Générateur
	pidGenerateur = ActiverGenerateur( 0, BALVoiture );
	cerr << "création de la tache générateur "<< pidGenerateur<<endl;

	// Création de la tâche Feu
	pidFeu = fork( );
	if ( pidFeu == 0 )
	{
		Feu( ATempoFeu, AEtatFeu, SFeu );
	}  
	cerr << "création de la tache Feu "<<endl;

	// Création de la tâche GestionPriorite

	pidGestionPrioriteOuest = fork( );
	if ( pidGestionPrioriteOuest == 0 )
	{
		IniGestionPriorite(BALVoiture,SFeu,AEtatFeu,OUEST);
	}
	pidGestionPrioriteEst = fork( );
	if ( pidGestionPrioriteEst == 0 )
	{
		IniGestionPriorite(BALVoiture,SFeu,AEtatFeu,EST);
	}
	pidGestionPrioriteNord = fork( );
	if ( pidGestionPrioriteNord == 0 )
	{
		IniGestionPriorite(BALVoiture,SFeu,AEtatFeu,NORD);
	}
	pidGestionPrioriteSud = fork( );
	if ( pidGestionPrioriteSud == 0 )
	{
		IniGestionPriorite(BALVoiture,SFeu,AEtatFeu,SUD);
	}

	// Création de la tâche Menu
	pidMenu = fork( );
	if ( pidMenu == 0 )
	{
		IniMenu(ATempoFeu,SFeu,pidGenerateur,BALVoiture );
	}
	cerr << "création de la tache Menu "<< pidMenu<<endl;
	
	// Attente de la mort de Menu
	int cr;
	waitpid ( pidMenu, &cr, 0 );
	if ( WIFEXITED ( cr ) )
	{
		cerr << "crdu = " << WEXITSTATUS ( cr ) << endl;
	}
	cerr << " La tâche Menu est morte !" << endl;

	// Mort de GestionPriorite
	int mortGestionPrioriteOuest;
	mortGestionPrioriteOuest = kill( pidGestionPrioriteOuest, SIGUSR2 );
	if (mortGestionPrioriteOuest)
	{
		cerr << "La tâche GestionPriorite n'est pas morte !" << endl;
	}
	int mortGestionPrioriteEst;
	mortGestionPrioriteEst = kill( pidGestionPrioriteEst, SIGUSR2 );
	if (mortGestionPrioriteEst)
	{
		cerr << "La tâche GestionPriorite n'est pas morte !" << endl;
	}
	int mortGestionPrioriteNord;
	mortGestionPrioriteNord = kill( pidGestionPrioriteNord, SIGUSR2 );
	if (mortGestionPrioriteNord)
	{
		cerr << "La tâche GestionPriorite n'est pas morte !" << endl;
	}
	int mortGestionPrioriteSud;
	mortGestionPrioriteSud = kill( pidGestionPrioriteSud, SIGUSR2 );
	if (mortGestionPrioriteSud)
	{
		cerr << "La tâche GestionPriorite n'est pas morte !" << endl;
	}

	// Mort de Feu
	int mortFeu;
	mortFeu = kill( pidFeu, SIGUSR2 );
	if (mortFeu)
	{
		cerr << "La tâche Feu n'est pas morte !" << endl;
	}

	// Mort de Generateur
	int mortGenerateur;
	kill(pidGenerateur,SIGCONT);
	mortGenerateur = kill( pidGenerateur, SIGUSR2 );
	if (mortGenerateur)
	{
		cerr << "La tâche Generateur n'est pas morte !" << endl;
	}

	// Mort de Heure
	int mortHeure;
	mortHeure = kill( pidHeure, SIGUSR2 );
	if (mortHeure)
	{
		cerr << "La tâche Heure n'est pas morte !" << endl;
	}

	// Attend la mort de ses enfants
	waitpid ( pidGestionPrioriteOuest, &cr, 0 );
	if ( WIFEXITED ( cr ) )
		{
			cerr << "crdu = " << WEXITSTATUS ( cr ) << endl;
		}
	waitpid ( pidGestionPrioriteEst, &cr, 0 );
	if ( WIFEXITED ( cr ) )
		{
			cerr << "crdu = " << WEXITSTATUS ( cr ) << endl;
		}
	waitpid ( pidGestionPrioriteNord, &cr, 0 );
	if ( WIFEXITED ( cr ) )
		{
			cerr << "crdu = " << WEXITSTATUS ( cr ) << endl;
		}
	waitpid ( pidGestionPrioriteSud, &cr, 0 );
	if ( WIFEXITED ( cr ) )
		{
			cerr << "crdu = " << WEXITSTATUS ( cr ) << endl;
		}
	waitpid ( pidGenerateur, &cr, 0 );
	if ( WIFEXITED ( cr ) )
		{
			cerr << "crdu = " << WEXITSTATUS ( cr ) << endl;
		}
	waitpid ( pidHeure, &cr, 0 );
	if ( WIFEXITED ( cr ) )
		{
			cerr << "crdu = " << WEXITSTATUS ( cr ) << endl;
		}
	waitpid ( pidFeu, &cr, 0 );
	if ( WIFEXITED ( cr ) )
		{
			cerr << "crdu = " << WEXITSTATUS ( cr ) << endl;
		}

	// Mort de BALVoiture
	msgctl ( BALVoiture, IPC_RMID, 0 );
	cerr << "BALVoiture detruite" << endl;


	// Mort de STempo Feu et SEtatFeu
	semctl ( SFeu, 0, IPC_RMID, 0 );
	cerr << "Sémaphore de controle des shm détruit" <<endl;
	//semctl ( SEtatFeu, 0, IPC_RMID, 0 );

	// Mort de MTempoFeu et MEtatFeu
	shmctl ( MTempoFeu, IPC_RMID, 0 );
	shmctl ( MEtatFeu, IPC_RMID, 0 );
	cerr << "Shms détruites" <<endl;

	// Mort des ressources écran et clavier : restitue les composants mais garde un affichage de l'écran
	TerminerApplication( false );
	cerr << "Appli terminée" << endl;
	kill (0,SIGUSR2);

} //----- fin de Nom

